package com.jwgf.smarowindingmachine_unity.logic;

import android.util.SparseArray;

import com.jwgf.Half485.modbusthreadpool.ModbusCommandManager;
import com.jwgf.Half485.modbusthreadpool.ModbusUtils;
import com.jwgf.Half485.modbusthreadpool.PLCData;
import com.jwgf.common.Utility;
import com.jwgf.fault.FaultRecorder;
import com.jwgf.fram.FramManager;
import com.jwgf.protocolstack.CommunicationStateListener.ReadSucceedListener;
import com.jwgf.protocolstack.ProtocolStack;
import com.jwgf.smarowindingmachine_unity.ui.SmaroWindingMachineActivity;

import java.io.IOException;
import java.util.Locale;

public class SmaroWindingMachineCanReadSucceedListener implements ReadSucceedListener {

    private static SmaroWindingMachineCanReadSucceedListener SmaroWindingMachineCanHandReadSucceedlistener = new SmaroWindingMachineCanReadSucceedListener();
    public static ProtocolStack canHandStack;
    private static FramManager fm = FramManager.getInstance();
    private MachineParameterSharedPreference sp = MachineParameterSharedPreference.getInstance();
    public String dofferVersion = "L0X.0P.V0.0";

    // 0x77
    private int d0536 = 0;

    // 0x7A
    private int d0540 = 0;
    private int d0550 = 0;
    private int d0551 = 0;

    private SparseArray<String> resultData = new SparseArray<String>();

    private long data63DC_bit4;

    private boolean[] spindleToken = new boolean[72];

    private SmaroWindingMachineCanReadSucceedListener() {
    }

    public static SmaroWindingMachineCanReadSucceedListener getInstance() {
        return SmaroWindingMachineCanHandReadSucceedlistener;
    }

    public boolean getSpindleToken(int spindle) {
        return spindleToken[spindle - 1];
    }

    public void setSpindleToken(int spindle, boolean isConnected) {
        spindleToken[spindle - 1] = isConnected;
    }

    @Override
    public void readSucceed(ProtocolStack ps, byte[] request, byte[] response) {
        int spindleId = (response[3] & 0xff) - 1;
        if ((spindleId < 1 || spindleId > 72) && spindleId != 0x9f) {
            return;
        }
        int cmd = response[2];
        int db = ((response[5] & 0xff) << 8) | (response[4] & 0xff);
        int dc = ((response[7] & 0xff) << 8) | (response[6] & 0xff);
        int dd = ((response[9] & 0xff) << 8) | (response[8] & 0xff);
        String key0 = spindleId + "-" + cmd + "-" + 0;
        String key1 = spindleId + "-" + cmd + "-" + 1;
        String key2 = spindleId + "-" + cmd + "-" + 2;
        switch (cmd) {
            case 0x60:
                Report.getInstance().parse60Cmd(spindleId, db, dc);
                try {
                    fm.putInt(key0, db);
                    fm.putInt(key1, dc);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                break;
            case 0x61:
                Report.getInstance().parse61Cmd(spindleId, db, dc, dd);
                try {
                    fm.putInt(key0, db);
                    fm.putInt(key1, dc);
                    fm.putInt(key2, dd);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                break;
            case 0x65:
                Report.getInstance().parse65Cmd(spindleId, db, dc, dd);
                break;
            case 0x64:
//                Report.getInstance().parse64Cmd(spindleId, dc);
//                try {
//                    fm.putInt(key0, db);
//                    fm.putInt(key1, dc);
//                    fm.putInt(key2, dd);
//                } catch (IOException e) {
//                    e.printStackTrace();
//                }
                break;
            case 0x67: {
                int spindle = db - 1;
                setSpindleToken(spindle, false);
            }
            break;
            case 0x62: {
                int oldDB = fm.getInt(key0, 0);
                int oldDC = fm.getInt(key1, 0);
                if (oldDC != dc) {
                    for (int i = 0; i < 7; i++) {
                        int newBit = (dc >> i) & 0x01;
                        if (newBit == 1 && i == 4) {
                            SmaroWindingMachineActivity.canHandStack.putPriorityCmd(CanCommand.initSpindle(spindleId));
                        }
                    }
                }
                Report.getInstance().parse62DB(spindleId, oldDB, db);
                Report.getInstance().parse62DC(spindleId, oldDC, dc);
                try {
                    fm.putInt(key0, db);
                    fm.putInt(key1, dc);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            break;
            case 0x63: {
                int oldDB = fm.getInt(key0, 0);
                int oldDC = fm.getInt(key1, 0);
                int oldDD = fm.getInt(key2, 0);
                if (oldDB != db) {
                    Report.getInstance().parse63DB(spindleId, oldDB, db);
                    for (int i = 0; i < 13; i++) {
                        int oldBit = (oldDB >> i) & 0x01;
                        int newBit = (db >> i) & 0x01;

                        int code = (cmd << 24) + (0 << 16) + (i << 8) + spindleId;
                        if (i == 12) {
                            if (newBit == 1 && oldBit == 0) {//故障开始
                                FaultRecorder.getInstance().startFaultRecord(FaultRecorder.FAULT_TYPE, code);
                            } else if (newBit == 0 && oldBit == 1) {//故障结束
                                FaultRecorder.getInstance().stopFaultRecord(FaultRecorder.FAULT_TYPE, code);
                            }
                        } else {
                            if (newBit == 1 && oldBit == 0) {//工艺报警开始
                                FaultRecorder.getInstance().startFaultRecord(FaultRecorder.PROCESS_TYPE, code);
                            } else if (newBit == 0 && oldBit == 1) {//工艺报警结束
                                FaultRecorder.getInstance().stopFaultRecord(FaultRecorder.PROCESS_TYPE, code);
//							}
                            }
                        }
                    }
                }
                if (oldDC != dc) {
                    Report.getInstance().parse63DC(spindleId, oldDC, dc);
                    if (sp.getValue(MachineParameterSharedPreference.PLC_TYPE, "0").equals("0")) {
                        data63DC_bit4 = Utility.BitUtils.setBitValue(data63DC_bit4, spindleId - 1, dc & 0x10);
                        ModbusCommandManager.getInstance().putNormalCmd(ModbusUtils.createWriteRegisterCmd((byte) 1, 65, Utility.ByteArrayUtils.long2SwapByteArray(data63DC_bit4)));
                    }
                    for (int i = 0; i < 16; i++) {
                        int oldBit = (oldDC >> i) & 0x01;
                        int newBit = (dc >> i) & 0x01;
                        int code = (cmd << 24) + (1 << 16) + (i << 8) + spindleId;
                        if (i == 0 || i == 1 || i == 2 || i == 3 || i == 4 || i == 15) {
                            if (newBit == 1 && oldBit == 0) {//红灯报警开始
                                FaultRecorder.getInstance().startFaultRecord(FaultRecorder.RED_LIGHT_TYPE, code);
                            } else if (newBit == 0 && oldBit == 1) {//红灯报警结束
                                FaultRecorder.getInstance().stopFaultRecord(FaultRecorder.RED_LIGHT_TYPE, code);
                            }
                        } else {
                            if (newBit == 1 && oldBit == 0) {//故障开始
                                FaultRecorder.getInstance().startFaultRecord(FaultRecorder.FAULT_TYPE, code);
                            } else if (newBit == 0 && oldBit == 1) {//故障结束
                                FaultRecorder.getInstance().stopFaultRecord(FaultRecorder.FAULT_TYPE, code);
                            }
                        }
                    }
                }
                if (oldDD != dd) {
                    Report.getInstance().parse63DD(spindleId, oldDD, dd);
                    for (int i = 0; i < 5; i++) {
                        int oldBit = (oldDD >> i) & 0x01;
                        int newBit = (dd >> i) & 0x01;
                        int code = (cmd << 24) + (2 << 16) + (i << 8) + spindleId;
                        if (newBit == 1 && oldBit == 0) {
                            FaultRecorder.getInstance().startFaultRecord(FaultRecorder.FAULT_TYPE, code);
                        } else if (newBit == 0 && oldBit == 1) {
                            FaultRecorder.getInstance().stopFaultRecord(FaultRecorder.FAULT_TYPE, code);
                        }
                    }
                }
                try {
                    fm.putInt(key0, db);
                    fm.putInt(key1, dc);
                    fm.putInt(key2, dd);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            break;
            case 0x57:
                dofferVersion = String.format(Locale.US, "L%dX.%dP.V%d.%d", db, dc, dd >> 8, dd & 0xff);
            case 0x76:
                String doffer_key0 = d0536 + "-" + cmd + "-" + 0;
                String doffer_key1 = d0536 + "-" + cmd + "-" + 1;
                int oldDB = fm.getInt(doffer_key0, 0);
                int oldDC = fm.getInt(doffer_key1, 0);
                if (oldDB != db) {
                    for (int i = 0; i < 16; i++) {
                        int oldBit = (oldDB >> i) & 0x01;
                        int newBit = (db >> i) & 0x01;
                        int code = (cmd << 24) + (0 << 16) + (i << 8) + d0536;
                        if (newBit == 1 && oldBit == 0) {
                            FaultRecorder.getInstance().startFaultRecord(FaultRecorder.DOFF_FAULT_TYPE, code);
                        } else if (newBit == 0 && oldBit == 1) {
                            FaultRecorder.getInstance().stopFaultRecord(FaultRecorder.DOFF_FAULT_TYPE, code);
                        }
                    }
                }
                if (oldDC != dc) {
                    for (int i = 0; i < 16; i++) {
                        int oldBit = (oldDC >> i) & 0x01;
                        int newBit = (dc >> i) & 0x01;
                        int code = (cmd << 24) + (1 << 16) + (i << 8) + d0536;
                        if (i != 5) {
                            if (newBit == 1 && oldBit == 0) {
                                FaultRecorder.getInstance().startFaultRecord(FaultRecorder.DOFF_FAULT_TYPE, code);
                            } else if (newBit == 0 && oldBit == 1) {
                                FaultRecorder.getInstance().stopFaultRecord(FaultRecorder.DOFF_FAULT_TYPE, code);
                            }
                        }
                    }
                }
                try {
                    fm.putInt(doffer_key0, db);
                    fm.putInt(doffer_key1, dc);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                break;
            case 0x77:
                d0536 = (dc & 0xff00) >> 8; //当前换筒锭号
                Report.getInstance().parse77Cmd(db);
                break;
            case 0x7A:
                if (d0540 == 0 && db == 1) {
                    //504,505
                    int d252 = PLCData.getInstance().getHoldingRegister(1, 252);
                    byte[] data = new byte[2];
                    data[0] = (byte) (d252 >> 8);
                    data[1] = (byte) (d252 | 0x20);
                    byte[] command = ModbusUtils.createWriteRegisterCmd((byte) 1, 252, data);
                    ModbusCommandManager.getInstance().putPriorityCmd(command);
                } else if (d0540 == 1 && db == 0) {
                    //504,505
                    int d252 = PLCData.getInstance().getHoldingRegister(1, 252);
                    byte[] data = new byte[2];
                    data[0] = (byte) (d252 >> 8);
                    data[1] = (byte) (d252 & (~0x20));
                    byte[] command = ModbusUtils.createWriteRegisterCmd((byte) 1, 252, data);
                    ModbusCommandManager.getInstance().putPriorityCmd(command);
                    // 小车落筒结束后，更新小板的主机运行状态
                    int d253 = PLCData.getInstance().getHoldingRegister(1, 253) > 0 ? 1 : 0;
                    SmaroWindingMachineActivity.canHandStack
                            .putPriorityCmd(MachineParameterSharedPreference.getInstance().createCanCmd75(
                                    0x75, 0x01, 502, String.valueOf(d253)));
                }
                d0540 = db;

                if (d0550 == 0 && dc == 1) {
                    int r20 = PLCData.getInstance().getHoldingRegister(1, 0xA);
                    r20 = Utility.BitUtils.setBitValue(r20, 9, 1);
                    byte[] data = ModbusUtils.createWriteRegisterCmd((byte) 1, 0xA, Utility.ByteArrayUtils.short2ByteArray((short) r20));
                    ModbusCommandManager.getInstance().putPriorityCmd(data);

                } else if (d0550 == 1 && dc == 0) {
                    int r20 = PLCData.getInstance().getHoldingRegister(1, 0xA);
                    r20 = Utility.BitUtils.setBitValue(r20, 9, 0);
                    byte[] data = ModbusUtils.createWriteRegisterCmd((byte) 1, 0xA, Utility.ByteArrayUtils.short2ByteArray((short) r20));
                    ModbusCommandManager.getInstance().putPriorityCmd(data);
                }
                d0550 = dc;

                if (d0551 == 0 && dd == 1) {
                    int r20 = PLCData.getInstance().getHoldingRegister(1, 0xA);
                    r20 = Utility.BitUtils.setBitValue(r20, 10, 1);
                    byte[] data = ModbusUtils.createWriteRegisterCmd((byte) 1, 0xA, Utility.ByteArrayUtils.short2ByteArray((short) r20));
                    ModbusCommandManager.getInstance().putPriorityCmd(data);

                } else if (d0551 == 1 && dd == 0) {
                    int r20 = PLCData.getInstance().getHoldingRegister(1, 0xA);
                    r20 = Utility.BitUtils.setBitValue(r20, 10, 0);
                    byte[] data = ModbusUtils.createWriteRegisterCmd((byte) 1, 0xA, Utility.ByteArrayUtils.short2ByteArray((short) r20));
                    ModbusCommandManager.getInstance().putPriorityCmd(data);
                }
                d0551 = dd;
                break;
            case 0x10:
                resultData.put(cmd << 8 | 0, String.valueOf(db));
                resultData.put(cmd << 8 | 1, String.valueOf(dc));
                resultData.put(cmd << 8 | 2, String.valueOf(dd));
                break;
            case 0x20:
                resultData.put(cmd << 8 | 0, String.valueOf(db));
                resultData.put(cmd << 8 | 1, String.valueOf(dc));
                resultData.put(cmd << 8 | 2, String.valueOf(dd));
                break;
            case 0x21:
                int changeTubeValue = (response[8] & 0xff);// 换管失败自启动次数
                int spliceFailedValue = (response[9] & 0xff);// 捻接失败自启动次数
                resultData.put(cmd << 8 | 0, String.valueOf(db));
                resultData.put(cmd << 8 | 1, String.valueOf(dc));
                resultData.put(cmd << 8 | 2, String.valueOf(changeTubeValue));
                resultData.put(cmd << 8 | 3, String.valueOf(spliceFailedValue));
                break;
            case 0x22:
                resultData.put(cmd << 8 | 0, String.valueOf(db));
                resultData.put(cmd << 8 | 1, String.valueOf(dc));
                resultData.put(cmd << 8 | 2, String.valueOf(dd));
                break;
            case 0x23:
                int accTime = (response[6] & 0xff);// 加速度时间百分比
                int speedIncrease = (response[7] & 0xff);// 速度增加百分比
                resultData.put(cmd << 8 | 0, String.valueOf(db));
                resultData.put(cmd << 8 | 1, String.valueOf(accTime));
                resultData.put(cmd << 8 | 2, String.valueOf(speedIncrease));
                resultData.put(cmd << 8 | 3, String.valueOf(dd));
                break;
            case 0x24:
                resultData.put(cmd << 8 | 0, String.valueOf(db));
                resultData.put(cmd << 8 | 1, String.valueOf(dc));
                resultData.put(cmd << 8 | 2, String.valueOf(dd));
                break;
            case 0x25:
                resultData.put(cmd << 8 | 0, String.valueOf(db));
                resultData.put(cmd << 8 | 1, String.valueOf(dc));
                resultData.put(cmd << 8 | 2, String.valueOf(dd));
                break;
            case 0x26:
                resultData.put(cmd << 8 | 0, String.valueOf(db));
                resultData.put(cmd << 8 | 1, String.valueOf(dc));
                resultData.put(cmd << 8 | 2, String.valueOf(dd));
                break;
            case 0x27:
                int tensSensorMode = (response[4] & 0xff);// 张力闭环控制
                int vssValue = (response[5] & 0xff);// VSS最小张力
                int tensionIncreaseValue = (response[6] & 0xff);// 启动增压
                int tensionValue = (response[7] & 0xff);// 张力值
                int upLimitValue = (response[8] & 0xff);// 上限控制
                int downLimitValue = (response[9] & 0xff);// 下限控制
                resultData.put(cmd << 8 | 0, String.valueOf(tensSensorMode));
                resultData.put(cmd << 8 | 1, String.valueOf(vssValue));
                resultData.put(cmd << 8 | 2, String.valueOf(tensionIncreaseValue));
                resultData.put(cmd << 8 | 3, String.valueOf(tensionValue));
                resultData.put(cmd << 8 | 4, String.valueOf(upLimitValue));
                resultData.put(cmd << 8 | 5, String.valueOf(downLimitValue));
                break;
            case 0x28:
                resultData.put(cmd << 8 | 0, String.valueOf(db));
                resultData.put(cmd << 8 | 1, String.valueOf(dc));
                resultData.put(cmd << 8 | 2, String.valueOf(dd));
                break;
            case 0x29:
                resultData.put(cmd << 8 | 0, String.valueOf(db));
                resultData.put(cmd << 8 | 1, String.valueOf(dc));
                resultData.put(cmd << 8 | 2, String.valueOf(dd));
                break;
            case 0x2A:
                resultData.put(cmd << 8 | 0, String.valueOf(db));
                resultData.put(cmd << 8 | 1, String.valueOf(dc));
                resultData.put(cmd << 8 | 2, String.valueOf(dd));
                break;
            case 0x2C:
                resultData.put(cmd << 8 | 0, String.valueOf(db));
                resultData.put(cmd << 8 | 1, String.valueOf(dc));
                resultData.put(cmd << 8 | 2, String.valueOf(dd));
                break;
            case 0x30:
                resultData.put(cmd << 8 | 0, String.valueOf(db));
                resultData.put(cmd << 8 | 1, String.valueOf(dc));
                resultData.put(cmd << 8 | 2, String.valueOf(dd));
                break;
            case 0x31:
                int logicValue = dc << 16 | db;
                resultData.put(cmd << 8 | 0, String.valueOf(logicValue));
                resultData.put(cmd << 8 | 2, String.valueOf(dd));
                break;
            case 0x32:
                resultData.put(cmd << 8 | 0, String.valueOf(db));
                resultData.put(cmd << 8 | 1, String.valueOf(dc));
                resultData.put(cmd << 8 | 2, String.valueOf(dd));
                break;
            case 0x33:
                resultData.put(cmd << 8 | 0, String.valueOf(db));
                resultData.put(cmd << 8 | 1, String.valueOf(dc));
                resultData.put(cmd << 8 | 2, String.valueOf(dd));
                break;
            default:
                break;
        }
    }

    public void clearQueryData() {
        resultData.clear();
        //由于值域中包含0,1，因此默认为3表示没有查到
        resultData.put(0x20 << 8 | 2, "3");
    }

    public String getQueryData(int key) {
        String result = null;
        result = resultData.get(key);
        if (result == null)
            result = "0";
        return result;
    }

}
